package com.yc.framework.security.handler;

import com.alibaba.fastjson2.JSON;
import com.yc.common.annotation.Log;
import com.yc.common.annotation.RateLimiter;
import com.yc.common.core.domain.AjaxResult;
import com.yc.common.core.domain.model.LoginUser;
import com.yc.common.enums.OperationType;
import com.yc.common.utils.StringUtil;
import com.yc.common.utils.WebUtil;
import com.yc.framework.manager.AsyncManager;
import com.yc.framework.manager.factory.AsyncFactory;
import com.yc.framework.web.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 自定义退出处理类 返回成功
 */
@Configuration
@Slf4j
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {

    @Autowired
    private TokenService tokenService;

    /**
     * 退出处理
     */
    @Log(module = "用户认证模块", type = OperationType.LOGOUT, description = "用户登出")
    @RateLimiter(permitsPerSecond = 3.0)
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException {

        try {
            // 获取请求头中的令牌
            String token = WebUtil.getToken();

            // 验证令牌是否存在
            if (StringUtil.isEmpty(token)) {
                log.warn("登出请求未携带访问令牌");
                response.setStatus(401);
                response.setContentType("application/json");
                response.setCharacterEncoding("utf-8");
                response.getWriter().print(JSON.toJSONString(AjaxResult.error(401, "未提供有效的访问令牌")));
                return;
            }

            // 获取当前用户
            LoginUser loginUser = tokenService.getLoginUser();

            try {
                if (loginUser == null) {
                    // 令牌无效或已过期
                    log.warn("使用无效令牌尝试登出");
                    response.setStatus(401);
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().print(JSON.toJSONString(AjaxResult.error(401, "无效的访问令牌或会话已过期")));
                    return;
                }

            } catch (Exception e) {
                // 记录错误日志
                log.error("登出处理异常: {}", e.getMessage(), e);
                // 返回错误响应
                response.setStatus(500);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().print(JSON.toJSONString(AjaxResult.error(500, "登出过程中遇到问题，请稍后再试")));
            }
            // 删除令牌并加入黑名单
            tokenService.deleteToken(loginUser.getTokenInfo().getTokenId());
            // 记录登出日志（异步）
            AsyncManager.me().execute(AsyncFactory.recordLogoutInfo(
                    loginUser.getUsername(), "Logout", "退出成功"));

            log.info("用户 [{}] 退出登录成功", loginUser.getUsername());
            // 响应登出成功
            response.setStatus(200);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().print(JSON.toJSONString(AjaxResult.success("退出成功")));
        } catch (Exception e) {

            log.error("登出过程中发生错误", e);
            // 返回错误响应
            response.setStatus(500);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().print(JSON.toJSONString(AjaxResult.error(500, "登出过程中遇到问题，请稍后再试")));
        }
    }
}